使用 Docker Compose
Docker Compose 是一款旨在帮助定义和共享多容器应用程序的工具。使用Compose,我们可以创建一个 YAML 文件来定义服务,然后使用一个命令将所有内容运转起来或将其分解。
使用 Compose 的最大好处是,你可以在文件中定义应用程序堆栈,将其保留在项目仓库的根目录(现在由版本控制)中,并轻松地使其他人为您的项目做出贡献。只需复制您的存储库并启动撰写应用即可。实际上,您可能会在 GitHub/GitLab 上看到很多项目正在执行此操作。
安装 Docker Compose
如果是安装了 Docker Desktop/Toolbox 在 Windows 或 Mac 上,则你已经拥有 Docker Compose 了。如果是 Linux ,则需要手动安装(教程)。
安装之后,可以看一下是否能运行。
docker-compose version
创建 Compose 文件
- 在应用项目的根目录下,创建一个名为
docker-compose.yml
的文件。 - 在组合文件中,首先定义架构版本。多数情况下,最好使用最新的支持版本。你可以在 Compose 文件参考 查看现存版本和兼容性列表。
version: "3.7"
- 接着,定义一系列的服务(或者叫容器)来运行我们的应用。
version: "3.7"
services:
定义应用服务
这是我们用来定义我们应用容器的命令。
docker run -dp 3000:3000 \
-w /app -v "$(pwd):/app" \
--network todo-app \
-e MYSQL_HOST=mysql \
-e MYSQL_USER=root \
-e MYSQL_PASSWORD=secret \
-e MYSQL_DB=todos \
node:12-alpine \
sh -c "yarn install && yarn run dev"
首先为容器定义服务的入口和镜像。我们可以给服务起任何名字。名字会自动成为一个网络别名,这将对定义 MySQL 服务非常有用。
version: "3.7"
services:
app:
image: node:12-alpine你会看到命令紧跟着
image
定义,但这两者顺序是可以变化的。version: "3.7"
services:
app:
image: node:12-alpine
command: sh -c "yarn install && yarn run dev"接着定义
ports
,我们将使用短语法,但也可以用长语法。version: "3.7"
services:
app:
image: node:12-alpine
command: sh -c "yarn install && yarn run dev"
ports:
- 3000:3000继续,我们通过
working_dir
和volumes
来定义工作目录(-w /app
)和挂载卷映射(-v "$(pwd):/app"
)。挂载卷也有长短语法。使用 Docker Compose 挂载卷定义的一个好处是,我们可以使用相对路径(当前目录)。
version: "3.7"
services:
app:
image: node:12-alpine
command: sh -c "yarn install && yarn run dev"
ports:
- 3000:3000
working_dir: /app
volumes:
- ./:/app最后,我们通过
environment
定义环境变量。version: "3.7"
services:
app:
image: node:12-alpine
command: sh -c "yarn install && yarn run dev"
ports:
- 3000:3000
working_dir: /app
volumes:
- ./:/app
environment:
MYSQL_HOST: mysql
MYSQL_USER: root
MYSQL_PASSWORD: secret
MYSQL_DB: todos
定义 MySQL 服务
容器命令为:
docker run -d \
--network todo-app --network-alias mysql \
-v todo-mysql-data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=secret \
-e MYSQL_DATABASE=todos \
mysql:5.7
首先定义一个新的服务叫做 mysql ,这将作为网络别名。
version: "3.7"
services:
app:
# The app service definition
mysql:
image: mysql:5.7接着,定义挂载卷映射。当我们使用
docker run
运行容器时,命名挂载卷会自动创建。但是,Compose 不会自动创建。我们需要在顶级volumes:
中定义挂载卷,并明确其在服务配置中的挂载点。这里可以仅提供挂载卷名字,来使用默认选项。还有更多的选项可以使用。version: "3.7"
services:
app:
# The app service definition
mysql:
image: mysql:5.7
volumes:
- todo-mysql-data:/var/lib/mysql
volumes:
todo-mysql-data:最后是环境变量。
```yml
version: "3.7"
services:
app:
# The app service definition
mysql:
image: mysql:5.7
volumes:
- todo-mysql-data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: todos
volumes:
todo-mysql-data:
```最后,
docker-compose.yml
应当是这样的:
version: "3.7"
services:
app:
image: node:12-alpine
command: sh -c "yarn install && yarn run dev"
ports:
- 3000:3000
working_dir: /app
volumes:
- ./:/app
environment:
MYSQL_HOST: mysql
MYSQL_USER: root
MYSQL_PASSWORD: secret
MYSQL_DB: todos
mysql:
image: mysql:5.7
volumes:
- todo-mysql-data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: todos
volumes:
todo-mysql-data:
运行我们的应用栈
确保没有应用或数据库正在运行(
docker ps
和docker rm -f <ids>
)。使用
docker-compose up
启动应用栈。我们使用-d
来后台运行应用。docker-compose up -d
运行后输出应当是这样的:
Creating network "app_default" with the default driver
Creating volume "app_todo-mysql-data" with default driver
Creating app_app_1 ... done
Creating app_mysql_1 ... done可以看到网络和挂载卷都创建了。默认情况下,Docker Compose 会自动为应用栈创建一个网络。
可以用
docker-compose logs -f
查看日志。你可以看到每个服务的日志形成一个流。这可以帮助你查看事件相关的问题。使用-f
修饰符来实时展示日志。日志大概长这样...
mysql_1 | 2019-10-03T03:07:16.083639Z 0 [Note] mysqld: ready for connections.
mysql_1 | Version: '5.7.27' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server (GPL)
app_1 | Connected to mysql db at host mysql
app_1 | Listening on port 3000如果想查看某个具体服务的日志,可以加上服务的名称,比如
docker-compose logs -f app
。
当应用启动时,实际上他会等待 MySQL 服务上线并尝试连接。Docker 没有任何内置支持来等待另一个容器完全启动,运行并准备就绪,然后再启动另一个容器。对于基于 Node 的项目,你可以使用 wait-port 依赖。别的语言可能有类似的框架。
在 Dashboard 中查看应用栈
在 Docker Dashboard 中,可以看到有个组叫 app 。这就是由 Docker Compose 创建的项目名。默认情况下,项目名就是 docker-compose.yml
所在目录的名字。
打开这个组,可以看到定义了两个容器。同时这两个容器的名字是描述性的,遵循 <project-name>_<service-name>_<replica-number>
的模板。
终止应用栈
可以用 docker-compose down
终止整个应用栈,或者点击 Docker Dashboard 中的垃圾桶。
默认情况下,挂载卷是不会随之移除的。可以添加
--volumes
来移除挂载卷。
同样的,Docker Dashboard 也不会移除挂载卷。